Un guide complet sur le Partage de ressources inter-origines (CORS), couvrant la configuration, les implications de sécurité et les bonnes pratiques pour les développeurs.
Partage de ressources inter-origines (CORS) : Configuration et bonnes pratiques de sécurité
Dans le monde du dĂ©veloppement web, la sĂ©curitĂ© est primordiale. Un aspect essentiel de la sĂ©curitĂ© web consiste Ă gĂ©rer la maniĂšre dont les pages web d'une origine peuvent accĂ©der Ă des ressources d'une origine diffĂ©rente. C'est lĂ qu'intervient le Partage de ressources inter-origines (CORS). Le CORS est une fonctionnalitĂ© de sĂ©curitĂ© des navigateurs qui empĂȘche les pages web d'effectuer des requĂȘtes vers un domaine diffĂ©rent de celui qui a servi la page. Ce mĂ©canisme est en place pour empĂȘcher les sites web malveillants d'accĂ©der Ă des donnĂ©es sensibles. Cet article fournit un guide complet sur le CORS, couvrant sa configuration, ses implications en matiĂšre de sĂ©curitĂ© et ses bonnes pratiques.
Comprendre la politique de mĂȘme origine (Same-Origin Policy)
Le CORS repose sur le fondement de la politique de mĂȘme origine (Same-Origin Policy), un mĂ©canisme de sĂ©curitĂ© fondamental mis en Ćuvre par les navigateurs web. La politique de mĂȘme origine empĂȘche les pages web d'effectuer des requĂȘtes vers un domaine diffĂ©rent de celui qui a servi la page. Deux URL sont considĂ©rĂ©es comme ayant la mĂȘme origine si elles ont le mĂȘme protocole (par ex., HTTP ou HTTPS), le mĂȘme hĂŽte (par ex., example.com) et le mĂȘme port (par ex., 80 ou 443). Par exemple :
http://example.comethttp://example.com/pathsont de la mĂȘme origine.http://example.comethttps://example.comsont d'origines diffĂ©rentes (protocoles diffĂ©rents).http://example.comethttp://www.example.comsont d'origines diffĂ©rentes (hĂŽtes diffĂ©rents).http://example.com:80ethttp://example.com:8080sont d'origines diffĂ©rentes (ports diffĂ©rents).
La politique de mĂȘme origine est conçue pour prĂ©venir les attaques de type Cross-Site Scripting (XSS), oĂč un site web malveillant injecte des scripts dans un site web de confiance pour voler des donnĂ©es utilisateur ou effectuer des actions non autorisĂ©es. Sans la politique de mĂȘme origine, un site web malveillant pourrait potentiellement accĂ©der aux informations de votre compte bancaire si vous Ă©tiez connectĂ© Ă votre portail bancaire en ligne dans un autre onglet.
Qu'est-ce que le Partage de ressources inter-origines (CORS) ?
Bien que la politique de mĂȘme origine soit cruciale pour la sĂ©curitĂ©, elle peut aussi ĂȘtre restrictive dans des scĂ©narios lĂ©gitimes oĂč des sites web ont besoin d'accĂ©der Ă des ressources provenant d'origines diffĂ©rentes. Par exemple, une application web hĂ©bergĂ©e sur example.com pourrait avoir besoin de rĂ©cupĂ©rer des donnĂ©es depuis une API hĂ©bergĂ©e sur api.example.net. Le CORS fournit un mĂ©canisme pour contourner la politique de mĂȘme origine de maniĂšre contrĂŽlĂ©e, permettant aux pages web de faire des requĂȘtes inter-origines lorsqu'elles sont explicitement autorisĂ©es par le serveur.
Le CORS fonctionne en ajoutant des en-tĂȘtes HTTP Ă la rĂ©ponse du serveur, indiquant quelles origines sont autorisĂ©es Ă accĂ©der Ă la ressource. Le navigateur vĂ©rifie ensuite ces en-tĂȘtes et bloque la requĂȘte si l'origine de la page web effectuant la requĂȘte n'est pas autorisĂ©e.
Comment fonctionne le CORS : Les en-tĂȘtes HTTP
Le CORS s'appuie sur des en-tĂȘtes HTTP spĂ©cifiques pour faciliter les requĂȘtes inter-origines. Voici les principaux en-tĂȘtes impliquĂ©s :
1. Origin (En-tĂȘte de requĂȘte)
L'en-tĂȘte Origin est envoyĂ© par le navigateur dans les requĂȘtes inter-origines. Il indique l'origine (protocole, hĂŽte et port) de la page web qui effectue la requĂȘte. Par exemple :
Origin: http://example.com
2. Access-Control-Allow-Origin (En-tĂȘte de rĂ©ponse)
L'en-tĂȘte Access-Control-Allow-Origin est l'en-tĂȘte le plus important du CORS. Il spĂ©cifie quelles origines sont autorisĂ©es Ă accĂ©der Ă la ressource. Il peut avoir l'une des valeurs suivantes :
- Une origine spécifique : Par exemple,
Access-Control-Allow-Origin: http://example.comn'autorise que les requĂȘtes provenant dehttp://example.com. *(joker) :Access-Control-Allow-Origin: *autorise les requĂȘtes de n'importe quelle origine. Cette option doit ĂȘtre utilisĂ©e avec prudence, car elle dĂ©sactive de fait la politique de mĂȘme origine pour cette ressource.
Exemple :
Access-Control-Allow-Origin: https://www.example.com
3. Access-Control-Allow-Methods (En-tĂȘte de rĂ©ponse)
L'en-tĂȘte Access-Control-Allow-Methods spĂ©cifie les mĂ©thodes HTTP (par ex., GET, POST, PUT, DELETE) qui sont autorisĂ©es dans la requĂȘte inter-origine. Ceci est requis pour les requĂȘtes de prĂ©-vĂ©rification (expliquĂ©es ci-dessous).
Exemple :
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
4. Access-Control-Allow-Headers (En-tĂȘte de rĂ©ponse)
L'en-tĂȘte Access-Control-Allow-Headers spĂ©cifie les en-tĂȘtes HTTP qui sont autorisĂ©s dans la requĂȘte inter-origine. Ceci est Ă©galement requis pour les requĂȘtes de prĂ©-vĂ©rification.
Exemple :
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
5. Access-Control-Allow-Credentials (En-tĂȘte de rĂ©ponse)
L'en-tĂȘte Access-Control-Allow-Credentials spĂ©cifie si le navigateur doit inclure les informations d'identification (par ex., cookies, en-tĂȘtes d'autorisation) dans la requĂȘte inter-origine. Il peut avoir l'une des deux valeurs : true ou false. Si true est dĂ©fini, l'en-tĂȘte Access-Control-Allow-Origin ne peut pas ĂȘtre dĂ©fini sur *. Il doit s'agir d'une origine spĂ©cifique.
Exemple :
Access-Control-Allow-Credentials: true
6. Access-Control-Max-Age (En-tĂȘte de rĂ©ponse)
L'en-tĂȘte Access-Control-Max-Age spĂ©cifie le nombre de secondes pendant lesquelles le navigateur peut mettre en cache les rĂ©sultats de la requĂȘte de prĂ©-vĂ©rification. Cela peut amĂ©liorer les performances en rĂ©duisant le nombre de requĂȘtes de prĂ©-vĂ©rification.
Exemple :
Access-Control-Max-Age: 3600
RequĂȘtes simples vs. requĂȘtes de prĂ©-vĂ©rification (Preflight)
Le CORS distingue deux types de requĂȘtes inter-origines : les requĂȘtes simples et les requĂȘtes de prĂ©-vĂ©rification.
RequĂȘtes simples
Une requĂȘte simple est une requĂȘte qui rĂ©pond aux critĂšres suivants :
- La méthode est
GET,HEAD, ouPOST. - Si la méthode est
POST, l'en-tĂȘteContent-Typeest l'un des suivants :application/x-www-form-urlencoded,multipart/form-data, outext/plain. - La requĂȘte ne dĂ©finit aucun en-tĂȘte personnalisĂ© (autre que ceux automatiquement dĂ©finis par le navigateur).
Pour les requĂȘtes simples, le navigateur envoie la requĂȘte directement au serveur. Le serveur rĂ©pond ensuite avec les en-tĂȘtes CORS appropriĂ©s. Si l'origine est autorisĂ©e, le navigateur traite la rĂ©ponse. Sinon, le navigateur bloque la rĂ©ponse Đž lĂšve une erreur.
RequĂȘtes de prĂ©-vĂ©rification (Preflight)
Une requĂȘte de prĂ©-vĂ©rification est envoyĂ©e par le navigateur avant d'effectuer la vĂ©ritable requĂȘte inter-origine si la requĂȘte ne rĂ©pond pas aux critĂšres d'une requĂȘte simple. Cela se produit gĂ©nĂ©ralement lorsque la requĂȘte utilise une mĂ©thode autre que GET, HEAD, ou POST, ou lorsque la requĂȘte dĂ©finit des en-tĂȘtes personnalisĂ©s.
La requĂȘte de prĂ©-vĂ©rification est une requĂȘte OPTIONS qui inclut les en-tĂȘtes suivants :
Origin: L'origine de la page web qui effectue la requĂȘte.Access-Control-Request-Method: La mĂ©thode HTTP qui sera utilisĂ©e dans la requĂȘte rĂ©elle.Access-Control-Request-Headers: Une liste sĂ©parĂ©e par des virgules des en-tĂȘtes personnalisĂ©s qui seront utilisĂ©s dans la requĂȘte rĂ©elle.
Le serveur rĂ©pond alors avec les en-tĂȘtes suivants :
Access-Control-Allow-Origin: L'origine qui est autorisĂ©e Ă accĂ©der Ă la ressource.Access-Control-Allow-Methods: Les mĂ©thodes HTTP qui sont autorisĂ©es dans la requĂȘte inter-origine.Access-Control-Allow-Headers: Les en-tĂȘtes HTTP qui sont autorisĂ©s dans la requĂȘte inter-origine.Access-Control-Max-Age: Le nombre de secondes pendant lesquelles le navigateur peut mettre en cache les rĂ©sultats de la requĂȘte de prĂ©-vĂ©rification.
Si le serveur rĂ©pond avec les en-tĂȘtes CORS appropriĂ©s, le navigateur procĂšde Ă la requĂȘte inter-origine rĂ©elle. Sinon, le navigateur bloque la requĂȘte et lĂšve une erreur.
Exemples de configuration CORS
L'implémentation de CORS varie en fonction de la technologie cÎté serveur que vous utilisez. Voici quelques exemples pour des langages et frameworks cÎté serveur courants :
Node.js avec Express
L'utilisation du middleware cors est une approche courante pour configurer CORS dans Node.js avec Express :
const express = require('express');
const cors = require('cors');
const app = express();
// Activer CORS pour toutes les origines
app.use(cors());
// Activer CORS pour une origine spécifique
// app.use(cors({ origin: 'http://example.com' }));
// Activer CORS avec des options
// app.use(cors({
// origin: ['http://example.com', 'http://localhost:3000'],
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
// allowedHeaders: ['Content-Type', 'Authorization'],
// credentials: true
// }));
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello from the API!' });
});
app.listen(3001, () => {
console.log('Server listening on port 3001');
});
Python avec Flask
Vous pouvez utiliser l'extension Flask-CORS pour configurer CORS dans Flask :
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# Activer CORS pour toutes les origines
CORS(app)
# Activer CORS pour des origines spécifiques
# CORS(app, origins=['http://example.com', 'http://localhost:3000'])
@app.route('/api/data')
def get_data():
return {'message': 'Hello from the API!'}
if __name__ == '__main__':
app.run(port=3001)
Java avec Spring Boot
Spring Boot offre plusieurs façons de configurer CORS. Une approche consiste à utiliser l'annotation @CrossOrigin :
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Origine spécifique
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "Hello from the API!";
}
}
// Configuration CORS globale (avec WebMvcConfigurer) :
// @Configuration
// public class CorsConfig implements WebMvcConfigurer {
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins("http://example.com", "http://localhost:3000")
// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("Content-Type", "Authorization")
// .allowCredentials(true)
// .maxAge(3600);
// }
// }
PHP
En PHP, vous pouvez dĂ©finir les en-tĂȘtes CORS directement dans votre script :
<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Content-Type: application/json");
$data = array("message" => "Hello from the API!");
echo json_encode($data);
?>
Considérations de sécurité pour CORS
Bien que CORS permette les requĂȘtes inter-origines, il est crucial de comprendre les implications de sĂ©curitĂ© et de l'implĂ©menter correctement pour Ă©viter les vulnĂ©rabilitĂ©s.
1. Ăviter d'utiliser Access-Control-Allow-Origin: * en production
L'utilisation du joker * dans l'en-tĂȘte Access-Control-Allow-Origin autorise les requĂȘtes de n'importe quelle origine, dĂ©sactivant de fait la politique de mĂȘme origine pour cette ressource. Cela peut exposer votre API Ă des sites web malveillants qui pourraient potentiellement voler des donnĂ©es utilisateur ou effectuer des actions non autorisĂ©es. Au lieu de cela, spĂ©cifiez les origines exactes qui sont autorisĂ©es Ă accĂ©der Ă la ressource. Par exemple, si votre application web est hĂ©bergĂ©e sur example.com et a besoin d'accĂ©der Ă une API hĂ©bergĂ©e sur api.example.com, dĂ©finissez l'en-tĂȘte sur Access-Control-Allow-Origin: http://example.com.
Exemple global : Imaginez une API de service financier dĂ©finissant Access-Control-Allow-Origin: *. Un site web malveillant pourrait alors effectuer des requĂȘtes vers cette API au nom d'un utilisateur connectĂ©, pouvant potentiellement transfĂ©rer des fonds Ă l'insu de l'utilisateur.
2. Valider l'en-tĂȘte Origin sur le serveur
MĂȘme si vous spĂ©cifiez une liste d'origines autorisĂ©es, il est important de valider l'en-tĂȘte Origin sur le serveur pour empĂȘcher les attaquants de falsifier l'origine. Un attaquant pourrait potentiellement envoyer une requĂȘte avec un en-tĂȘte Origin falsifiĂ© pour contourner les vĂ©rifications CORS. Pour attĂ©nuer ce risque, comparez l'en-tĂȘte Origin avec une liste d'origines de confiance cĂŽtĂ© serveur. Si l'origine ne figure pas dans la liste, rejetez la requĂȘte.
Exemple global : Considérez une plateforme de commerce électronique. Un attaquant pourrait tenter d'imiter l'Origin d'une vitrine légitime pour accéder à des données clients sensibles depuis l'API de la plateforme.
3. Soyez prudent avec Access-Control-Allow-Credentials: true
Si vous dĂ©finissez Access-Control-Allow-Credentials: true, l'en-tĂȘte Access-Control-Allow-Origin ne peut pas ĂȘtre dĂ©fini sur *. Il doit s'agir d'une origine spĂ©cifique. C'est parce que l'autorisation des informations d'identification de n'importe quelle origine peut crĂ©er un risque de sĂ©curitĂ©, car cela pourrait permettre Ă des sites web malveillants d'accĂ©der aux donnĂ©es des utilisateurs s'ils parviennent Ă tromper un utilisateur pour qu'il visite leur site alors qu'il est Ă©galement connectĂ© au site web cible. Ce paramĂštre est important lors du traitement de cookies ou d'en-tĂȘtes d'autorisation.
Exemple global : Une plateforme de mĂ©dias sociaux autorisant les requĂȘtes inter-origines avec des informations d'identification nĂ©cessite une gestion prudente pour empĂȘcher l'accĂšs non autorisĂ© aux comptes des utilisateurs.
4. Configurer correctement Access-Control-Allow-Methods et Access-Control-Allow-Headers
N'autorisez que les mĂ©thodes et en-tĂȘtes HTTP nĂ©cessaires pour les requĂȘtes inter-origines. Si vous n'avez besoin que d'autoriser les requĂȘtes GET et POST, n'autorisez pas PUT, DELETE, ou d'autres mĂ©thodes. De mĂȘme, n'autorisez que les en-tĂȘtes spĂ©cifiques dont votre application a besoin. Des configurations trop permissives peuvent augmenter le risque d'attaques.
Exemple global : Un systĂšme CRM ne devrait exposer que les points de terminaison d'API et les en-tĂȘtes nĂ©cessaires aux intĂ©grations tierces autorisĂ©es, minimisant ainsi la surface d'attaque.
5. Utiliser HTTPS pour une communication sécurisée
Utilisez toujours HTTPS pour une communication sĂ©curisĂ©e entre le navigateur et le serveur. HTTPS chiffre les donnĂ©es transmises entre le navigateur et le serveur, empĂȘchant l'Ă©coute clandestine et les attaques de l'homme du milieu. L'utilisation de HTTP peut exposer des donnĂ©es sensibles aux attaquants, mĂȘme si CORS est configurĂ© correctly.
Exemple global : Les applications de santé doivent utiliser HTTPS pour protéger les données des patients transmises entre différentes origines.
6. Politique de sécurité du contenu (CSP)
Bien que non directement liĂ©e Ă CORS, la Politique de sĂ©curitĂ© du contenu (CSP) est un autre mĂ©canisme de sĂ©curitĂ© important qui peut aider Ă prĂ©venir les attaques XSS. La CSP vous permet de dĂ©finir une liste blanche de sources Ă partir desquelles le navigateur est autorisĂ© Ă charger des ressources. Cela peut aider Ă empĂȘcher les attaquants d'injecter des scripts malveillants dans votre site web, mĂȘme s'ils parviennent Ă contourner d'autres mesures de sĂ©curitĂ©.
Exemple global : Les institutions financiÚres emploient souvent des politiques CSP strictes pour limiter les sources de contenu chargées sur leurs portails bancaires en ligne, réduisant ainsi le risque d'attaques XSS.
ProblÚmes courants avec CORS et dépannage
Les erreurs CORS peuvent ĂȘtre frustrantes Ă dĂ©boguer. Voici quelques problĂšmes courants et comment les rĂ©soudre :
1. "Aucun en-tĂȘte 'Access-Control-Allow-Origin' n'est prĂ©sent sur la ressource demandĂ©e."
C'est l'erreur CORS la plus courante. Elle indique que le serveur ne renvoie pas l'en-tĂȘte Access-Control-Allow-Origin dans sa rĂ©ponse. Assurez-vous que le serveur est configurĂ© pour envoyer les bons en-tĂȘtes CORS pour l'origine de la page web qui effectue la requĂȘte. VĂ©rifiez votre code cĂŽtĂ© serveur et vos fichiers de configuration.
2. "La rĂ©ponse Ă la requĂȘte de prĂ©-vĂ©rification ne passe pas le contrĂŽle d'accĂšs : Elle n'a pas de statut HTTP ok."
Cette erreur indique que la requĂȘte de prĂ©-vĂ©rification a Ă©chouĂ©. Cela peut se produire si le serveur ne rĂ©pond pas aux requĂȘtes OPTIONS ou si le serveur renvoie un code de statut d'erreur (par ex., 404, 500) en rĂ©ponse Ă la requĂȘte de prĂ©-vĂ©rification. Assurez-vous que votre serveur est configurĂ© pour gĂ©rer les requĂȘtes OPTIONS et qu'il renvoie un code de statut 200 OK.
3. "La rĂ©ponse Ă la requĂȘte de prĂ©-vĂ©rification ne passe pas le contrĂŽle d'accĂšs : La valeur de l'en-tĂȘte 'Access-Control-Allow-Origin' dans la rĂ©ponse ne doit pas ĂȘtre le joker '*' lorsque le mode des informations d'identification de la requĂȘte est 'include'."
Cette erreur se produit lorsque vous essayez d'envoyer des informations d'identification (par ex., des cookies) dans une requĂȘte inter-origine et que l'en-tĂȘte Access-Control-Allow-Origin est dĂ©fini sur *. Comme mentionnĂ© prĂ©cĂ©demment, vous ne pouvez pas utiliser le joker * lors de l'envoi d'informations d'identification. Vous devez spĂ©cifier l'origine exacte qui est autorisĂ©e Ă accĂ©der Ă la ressource.
4. Mise en cache du navigateur
Les navigateurs peuvent mettre en cache les rĂ©ponses CORS, ce qui peut entraĂźner un comportement inattendu si la configuration CORS change. Pour Ă©viter les problĂšmes de mise en cache, dĂ©finissez l'en-tĂȘte Cache-Control dans la rĂ©ponse sur no-cache, no-store, ou max-age=0. Vous pouvez Ă©galement utiliser l'en-tĂȘte Access-Control-Max-Age pour contrĂŽler la durĂ©e de mise en cache des rĂ©sultats de la requĂȘte de prĂ©-vĂ©rification par le navigateur.
Alternatives Ă CORS
Bien que CORS soit la mĂ©thode standard pour activer les requĂȘtes inter-origines, il existe des alternatives que vous pouvez envisager dans certains scĂ©narios :
1. JSON avec remplissage (JSONP)
JSONP est une technique qui utilise la balise <script> pour contourner la politique de mĂȘme origine. JSONP fonctionne en enveloppant les donnĂ©es JSON dans un appel de fonction JavaScript. Le navigateur exĂ©cute ensuite la fonction JavaScript, en passant les donnĂ©es JSON en argument. JSONP est plus simple Ă mettre en Ćuvre que CORS, mais il a quelques limitations. Il ne prend en charge que les requĂȘtes GET, et il est moins sĂ©curisĂ© que CORS.
2. Proxy inverse
Un proxy inverse est un serveur qui se place devant votre serveur d'API et lui transmet les requĂȘtes. Le proxy inverse peut ĂȘtre configurĂ© pour ajouter les en-tĂȘtes CORS nĂ©cessaires Ă la rĂ©ponse, cachant ainsi les requĂȘtes inter-origines au navigateur. Cette approche peut ĂȘtre utile si vous n'avez pas le contrĂŽle sur le serveur d'API ou si vous souhaitez simplifier la configuration CORS.
Conclusion
Le Partage de ressources inter-origines (CORS) est un mécanisme de sécurité crucial qui permet aux pages web d'accéder à des ressources provenant de différentes origines de maniÚre contrÎlée. Comprendre comment CORS fonctionne et l'implémenter correctement est essentiel pour créer des applications web sécurisées et fiables. En suivant les bonnes pratiques décrites dans cet article, vous pouvez gérer efficacement le CORS et protéger vos API contre les accÚs non autorisés.
N'oubliez pas de toujours donner la prioritĂ© Ă la sĂ©curitĂ© lors de la configuration de CORS. Ăvitez d'utiliser des jokers, validez l'en-tĂȘte Origin, et utilisez HTTPS pour une communication sĂ©curisĂ©e. En prenant ces prĂ©cautions, vous pouvez vous assurer que vos applications web sont protĂ©gĂ©es contre les attaques inter-sites.
Ce guide complet fournit une base solide pour comprendre le CORS. Référez-vous toujours à la documentation officielle de votre technologie cÎté serveur spécifique pour les informations les plus à jour et les bonnes pratiques. Restez informé des menaces de sécurité émergentes et adaptez votre configuration CORS en conséquence.